package com.atguigu.cloud.gateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 全局请求认证过滤器
 * <p>
 * 该过滤器作为Spring Cloud Gateway的全局拦截器，用于验证请求中是否包含有效的用户名参数。
 * 如果请求缺少username参数，将返回401未授权状态码。
 * </p>
 *
 * @author Taeyang
 * @date 2025/4/5
 */
// @Component // 声明为Spring组件，Spring会自动扫描并注册该过滤器到应用上下文，无需在配置文件中显式声明或启用
public class AuthorizationFilter implements GlobalFilter, Ordered {

    /**
     * 全局过滤方法
     * <p>
     * 该方法会在每个请求经过网关时被调用，执行认证检查逻辑。
     * </p>
     *
     * @param exchange 当前请求上下文，包含请求/响应对象
     * @param chain    过滤器链，用于将请求传递给下一个过滤器或目标服务
     * @return Mono<Void> 响应式流处理结果
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        System.out.println("AuthorizationFilter Request ......");

        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        // 从查询参数中获取username
        String username = request.getQueryParams().getFirst("username");

        // 认证检查逻辑
        if (!StringUtils.hasText(username)) {
            // 直接抛出异常
            // throw new RuntimeException("No username in request");

            // 设置未授权状态码并终止请求处理
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }

        // 放行请求（继续执行过滤器链）
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            System.out.println("AuthorizationFilter Response ......");
        }));
    }

    /**
     * 过滤器执行优先级配置
     * <p>
     * 返回的整数值越小，过滤器优先级越高。
     * 0表示最高优先级，会最先执行。
     * </p>
     *
     * @return 过滤器执行顺序值
     */
    @Override
    public int getOrder() {
        return 0;
    }
}